home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 090 / byte0687.arc / CLOCKSET.ASM < prev    next >
Assembly Source File  |  1986-11-20  |  36KB  |  1,135 lines

  1. ******************
  2. *                *
  3. *  CLOCKSET.ASM  *   Set Time of Clock Cartridge
  4. *                *   <=> PUBLIC DOMAIN 09-SEP-86 <=>
  5. ******************
  6. *
  7. *** created:  03-AUG-86 by  Tim Hunkler / Solar Powered Software
  8. *
  9. ROM3    equ    $FA0000        ; ROM3 select strobe
  10. ROM4    equ    $FB0000        ; ROM4 select strobe
  11. READ    equ    0        ; control for READ access (A6=0)
  12. WRT    equ    64        ; control for WRITE access (A6=1)
  13. *
  14. * --- Function call definitions for GEM/AES calls
  15. *
  16. APPL_INI    equ 0        ; Application initialization
  17. APPL_EXI    equ 1        ; Application exit
  18. OBJC_DRA    equ 2        ; Object draw
  19. FORM_DO        equ 3        ; Form:  Do
  20. FORM_DIA    equ 4        ; Form:  Dialog
  21. FORM_ALE    equ 5        ; Form:  Alert
  22. FORM_CEN    equ 6        ; Form:  Center
  23. GRAF_MOU    equ 7        ; Graphics:  Mouse Form
  24. *
  25. * --- Offset definitions for dynamic storage 
  26. *
  27. params    equ    $0000    ; table of array pointers
  28. control    equ    $0018    ; array of control counts
  29. global    equ    $0022    ; array of global variables
  30. int_in    equ    $0040    ; array of integers in
  31. int_out    equ    $0060    ; array of integers out
  32. addr_in    equ    $006E    ; array of addresses in
  33. addr_out equ    $0072    ; array of addresses out
  34. buffer    equ    $0076    ; buffer to receive clock chip data
  35. ap_id    equ    $0026    ; application ID, one of the globals
  36. stack    equ    $0486    ; stack area (grows downward)
  37. xx    equ    $048A    ; temp area to receive x,y,w,h info
  38. sz_stor    equ    $0492    ; size of dynamic storage needs
  39.  
  40. * ===============================
  41. * ----- PROGRAM ENTRY POINT -----
  42. * ===============================
  43.  
  44. x:    lea    storage(pc),a5    ; load base of dynamic storage
  45.     lea    stack(a5),sp    ; establish a stack
  46. *
  47. * --- release all memory not needed
  48. *
  49.     move.l    #(storage-x+256+sz_stor),-(sp) ; push num bytes to keep
  50.     pea    x-256(pc)    ; push address of memory to keep
  51.     clr.w    -(sp)        ; push filler
  52.     move.w    #74,-(sp)    ; push function code = memory shrink
  53.     trap    #1        ; call the system
  54.     lea    12(sp),sp    ; fix the stack
  55. *
  56. * --- initialize GEM/AES parameter block
  57. *
  58.     lea    params+24(a5),a6    ; address end of block
  59.     lea    control(a5),a0        ; first pntr
  60.     lea    global(a5),a1        ; second pntr
  61.     lea    int_in(a5),a2        ; third pntr
  62.     lea    int_out(a5),a3        ; fourth pntr
  63.     lea    addr_in(a5),a4        ; fifth pntr
  64.     lea    addr_out(a5),a5        ; sixth pntr
  65.     movem.l    a0-a5,-(a6)        ; fill data block
  66. *
  67. * --- zero some areas in =global=
  68. *
  69.     moveq     #14,d0        ; loop for 15 words
  70. zgbl:    clr.w     (a1)+        ; clear entire array
  71.     dbf     d0,zgbl
  72. *
  73. * --- initialize base and data pointers and start program
  74. *
  75.     lea    x(pc),a6     ; A6 will be program base register
  76.     lea    storage(pc),a5     ; A5 will be data storage base register
  77. *
  78. * --- begin regular program code
  79. *
  80. START:    bsr    _appl_in    ; initialize application
  81.     bsr    _mouse        ; change mouse pointer to an arrow
  82. *
  83. * --- read info from the clock cartridge
  84. *
  85. rdcart:    lea    buffer(a5),a2    ; load addr of buffer to be filled
  86.     bsr    r_clock        ; read time from the clock cartridge
  87.     beq.s    hwok        ; branch if all went ok
  88. *
  89. * --- clock's time was bad or the hardware is not working
  90. *
  91.     lea    warning(pc),a0    ; address warning message 
  92.     bsr    _alert        ; and display the message
  93. *
  94. * --- process dialog menu
  95. *
  96. hwok:    bsr    format        ; format time/date into dialog strings
  97.     bsr    dialog        ; display and process the dialog
  98. *
  99. * --- determine which exit button was used
  100. *
  101.     moveq     #1,d3        ; outer box = object #1
  102.     bsr     tstnclr    ; was outer box selected?
  103.     bne.s     rdcart        ; yes, then update the time displayed
  104.  
  105.     moveq     #12,d3        ; SET = object #12
  106.     bsr     tstnclr    ; was SET button selected?
  107.     beq.s     if13        ; no, branch
  108.     bsr     set_clk    ; yes, change time
  109.     bra.s     rdcart
  110.  
  111. if13:    bsr     tstnclr    ; was button = EXIT?
  112.     beq.s     rdcart        ; no, then update menu
  113. *
  114. * --- exit this program
  115. *
  116.     bsr     _appl_ex    ; notify GEM of application exit
  117.  
  118.     clr.w     -(sp)        ; function code = exit
  119.     trap     #1        ; call TOS and never return!
  120.     
  121. * =====================================
  122. * ===== w_clock :  write to clock =====
  123. * =====================================
  124. *
  125. *    in:  D0.B = data to be written
  126. *            D1.W = register address x 2 to be written to
  127. *
  128. *      out:  A3.L = pointer to clock address latch
  129. *            A4.L = pointer to clock chip select
  130. *         D1.W = increased by 2
  131. *            D0.W = data present prior to write
  132. *            cc's : set by D0
  133. *
  134. *  changed:  A0,D2
  135. *
  136. *  This subroutine is used to write data to the clock chip.  The data
  137. *  to be written is passed in the lower 4 bits of D0 and 2 times the
  138. *  clock register to be accessed in passed in D1.
  139. *
  140. w_clock:
  141.     lea    ROM3,a3        ; LATCH address
  142.     lea    ROM4,a4        ; CS low strobe
  143. *
  144. * --- form the clock register address
  145. *
  146. wcep:    lea    0(a3,d1.w),a0    ; form proper address
  147. *
  148. * --- mask off 4 bit data and align it into bits 12..15
  149. *
  150.     moveq    #15,d2        ; load mask
  151.     and.w    d0,d2        ; mask of 4 bit data item
  152.     ror.w    #4,d2        ; rotate to upper bits
  153. *
  154. * --- latch address, data, and enable writes to the chip
  155. *
  156.     move.b    WRT(a0,d2.l),d0    ; read old data, latch new data
  157. *
  158. * --- turn chip select on to start the write operation
  159. *
  160.     tst.w    (a4)        ; set chip select low
  161.     addq.w    #2,d1        ; update register address
  162. *
  163. * --- turn off write enable, turn off chip select, but hold data
  164. *
  165.     tst.b    READ(a0,d2.l)    ; set chip select high
  166.     andi.w    #$000F,d0    ; mask off 4 bit data and set cond codes
  167.     rts
  168.  
  169. * =====================================
  170. * ===== r_clock : read from clock =====
  171. * =====================================
  172. *
  173. *       in:  A2.L = address of 16 byte buffer to be filled
  174. *
  175. *      out:  D0.L = 0 if all OK, else -1
  176. *            cc's : set by D0
  177. *            (A2) ---> [ flag bits   ]    leap count, AM/PM, 12/24 hr.
  178. *                 +1   [ day of week ]  1=Sunday
  179. *                 +2   [ year x 10   ]    00 = 1980, 01 = 1981, etc.
  180. *                 +3   [ year x 1    ]
  181. *                 +4   [ month x 10  ]
  182. *                 +5   [ month x 1   ]
  183. *                      [ day x 10    ]
  184. *                      [ day x 1     ]
  185. *                      [ hour x 10   ]
  186. *                      [ hour x 1    ]
  187. *                      [ minute x 10 ]
  188. *                      [ minute x 1  ]
  189. *                      [ second x 10 ]
  190. *                      [ second x 1  ]
  191. *                 +14  [ .1 seconds  ]
  192. *                 +15  [ junk byte   ]
  193. *
  194. *  changed:  A0,A4,D1,D2
  195. *
  196. *  This subroutine reads all time and date registers from the clock chip
  197. *  and fills a 16 byte buffer whose address was passed in A2.  As the
  198. *  information is read it is added up.  Invalid sums typically indicate
  199. *  a dead battery or a clock cartridge which is not present and are
  200. *  indicated by returning a -1 in register D0 and the condition codes.
  201. *  A data changed bit is checked and if the time changed while the read
  202. *  operation was in progress the operation is repeated.
  203. *
  204. r_clock:
  205.     lea     ROM4,a4    ; set pointer for ROM4 strobe
  206.     lea     ROM3,a0    ; set pntr to register 0
  207.     lea     16(a2),a2    ; point to end of buffer to fill
  208.     moveq     #0,d1        ; set accumulator to zero
  209. *
  210. * --- preload the register address in the latch
  211. *
  212.     tst.w     (a0)+        ; set register selection to 0
  213. *
  214. * --- loop and read clock registers 0..15
  215. *
  216.     moveq     #15,d2        ; loop count = 16
  217. fetch:    tst.w     (a4)        ; set chip select on
  218.     moveq     #15,d0        ; load 4 bit data mask
  219.     and.w     (a0)+,d0    ; get data, set next addr, select off
  220.     move.b     d0,-(a2)    ; store data in buffer
  221.     add.w     d0,d1        ; add up all data values
  222.     dbf     d2,fetch    ; and repeat for 16 items
  223. *
  224. * --- retrieve data changed flag (zero indicates no change occurred)
  225. *
  226.     tst.w     (a4)        ; set CS low with register select = 0
  227.     moveq     #8,d0        ; load mask
  228.     and.w     (a0),d0    ; get flag, nxt addr = 2, select = off
  229. *
  230. * --- if no clock present we generally accumulate 16 x 15 = 240
  231. *
  232.     cmpi.w     #125,d1    ; does accumulation indicate bad data?
  233.     ble.s     nwflg        ; no, branch
  234.     moveq     #-1,d0        ; yes, set error flag
  235. *
  236. * --- test data changed flag and reread the time if necessary
  237. *
  238. nwflg:    tst.w     d0        ; was data changed (or an error)?
  239.     bgt.s     r_clock    ; yes, then repeat the time reading
  240.     rts            ; no, exit with cond codes set
  241.  
  242. * =========================================================
  243. * ===== format:  format clock data buffer into dialog =====
  244. * =========================================================
  245. *
  246. *    in:  A2.L = addr of 16 byte buffer returned by "r_clock"
  247. *      out:  none
  248. *  changed:  A0,A1,A2,A3,D0,D1,D2,D3
  249. *
  250. *  This subroutine takes the contents of the 16 byte buffer filled
  251. *  in by "r_clock" and uses it to format information in the dialog
  252. *  menu.  The 7 radio buttons which indicate the day of the week are
  253. *  set based on the day of the week value of 1..7.  The date is
  254. *  formatted and the date string is formed.  And also the time is
  255. *  formatted and the time string is formed.
  256. *
  257. format:    lea     tree(pc),a3    ; address dialog tree
  258. *
  259. * --- clear radio buttons
  260. *
  261.     moveq     #6,d2        ; loop for 7 days of the week
  262.     moveq     #5,d3        ; start with button for SUN
  263. fmtclr:    bsr     tstnclr    ; clear buttons for SUN..SAT
  264.     dbra     d2,fmtclr    ; repeat till done
  265. *
  266. * --- set radio button for day of the week
  267. *
  268.     moveq     #7,d3        ; load 3 bit mask
  269.     and.w     (a2)+,d3    ; get day of week, 1..7
  270.     addq.w     #4,d3        ; convert to object number 5..11
  271.     bsr     setsel        ; set button for SUN..SAT
  272. *
  273. * --- form date string:  MM/DD/YY
  274. *
  275.     lea     s_date+4(pc),a1 ; access date string
  276.     move.b     (a2)+,(a1)    ; copy tens digit of year
  277.     addi.b     #8,(a1)+    ; modify for 1980 baseline
  278.     move.b     (a2)+,(a1)+    ; copy ones digit of year
  279.  
  280.     subq.l     #6,a1        ; back up to access month
  281.     move.b     (a2)+,(a1)+    ; move two digits of month
  282.     move.b     (a2)+,(a1)+
  283.  
  284.     move.b     (a2)+,(a1)+    ; move two digits of day-of-month
  285.     move.b     (a2)+,(a1)+
  286. *
  287. * --- form time string:  HH:MM:SS AM
  288. *
  289.     moveq     #'A',d2    ; preload AM/PM indicator as AM
  290.     moveq     #15,d0        ; load a mask
  291.     and.b     (a2)+,d0    ; get tens digit of hour
  292.     mulu     #10,d0
  293.     add.b     (a2)+,d0    ; add in ones digit, hours in D0.W
  294.  
  295.     lea     s_time+2(pc),a1 ; address minute field
  296.     move.b     (a2)+,(a1)+    ; move two digits of minutes
  297.     move.b     (a2)+,(a1)+
  298.  
  299.     move.b     (a2)+,(a1)+    ; move two digits of seconds
  300.     move.b     (a2)+,(a1)+
  301.  
  302.     tst.w     d0        ; is it midnight to 1:00 am ?
  303.     bne.s     ampm        ; no, skip ahead
  304.     moveq     #12,d0        ; yes, change from 00:xx to 12:xx
  305.     bra.s     AM
  306.  
  307. ampm:    cmpi.w     #12,d0        ; does hour indicate PM?
  308.     blt.s     AM        ; for 00:00 to 11:59 no change
  309.     beq.s     noon        ; for 12:00 to 12:59 change flag to 'PM'
  310.     subi.w     #12,d0        ; for 13:00 to 23:59 reduce by 12 hours
  311. noon:    moveq     #'P',d2    ; change flag to PM
  312.  
  313. AM:    move.b     d2,(a1)+    ; store A or P for AM/PM
  314.     
  315.     subq.l     #7,a1        ; point to hours field
  316.     divu     #10,d0        ; split hours into tens and ones digit
  317.     move.b     d0,(a1)+    ; store tens digit
  318.     swap     d0        ; access ones digit
  319.     move.b     d0,(a1)    ; store ones digit
  320.     subq.l     #1,a1        ; adjust pntr to time string
  321.     bsr.s     convrt        ; convert binary into characters
  322.  
  323.     lea     s_date(pc),a1    ; adjust pntr to date string
  324. convrt:    moveq     #5,d1        ; do 6 digits
  325. cvt:    ori.b     #'0',(a1)+    ; convert byte into ASCII
  326.     dbra     d1,cvt
  327.     rts
  328.  
  329. * =======================================================
  330. * ===== set_clk :  Set time/date in clock cartridge =====
  331. * =======================================================
  332. *
  333. *    in:  A3.L = address of dialog tree
  334. *      out:  none
  335. *  changed:
  336. *
  337. *  This subroutine uses the time and date present on the dialog
  338. *  menu to set the time and date for GEM and TOS.  It then converts
  339. *  this information into the appropriate fields of the 16 byte table
  340. *  filled in by 'r_clock' and uses this table to alter the time and
  341. *  date of the MM58274 clock chip.
  342. *
  343. set_clk:
  344.     bsr     set_time    ; set time for TOS and GEM
  345.     bne.s     tsok        ; branch if all went ok
  346.  
  347.     lea     badtime(pc),a0 ; address error message
  348.     bra     _alert        ; display alert then return
  349.  
  350. tsok:    lea     buffer-1(a5),a2 ;    ; access byte prior to buffer
  351.     move.b     #1,(a2)+    ; install command = %0001
  352.     clr.b     (a2)+        ; install command = %0000
  353. *
  354. * --- figure out which day of the week is indicated
  355. *
  356.     moveq     #5,d3        ; select button = SUN
  357. sfdow:    bsr     tstnclr    ; is it selected?
  358.     beq.s     sfdow        ; no, then try next button
  359.     subq.w     #5,d3        ; convert SUN..SAT into 1..7
  360.     move.b     d3,(a2)+    ; and store
  361. *
  362. * --- convert the date string into binary nibbles
  363. *
  364.     lea     s_date+4(pc),a0 ; access tens digit of year
  365.     subq.b     #8,(a0)    ; convert 1980 into 00
  366.     move.b     (a0)+,(a2)+    ; move two year digits
  367.     move.b     (a0)+,(a2)+
  368.  
  369.     subq.l     #6,a0        ; access month
  370.     move.b     (a0)+,(a2)+    ; move two month digits
  371.     move.b     (a0)+,(a2)+
  372.  
  373.     move.b     (a0)+,(a2)+    ; move two day digits
  374.     move.b     (a0)+,(a2)+
  375. *
  376. * --- convert the time string into binary nibbles
  377. *
  378.     lea     s_time(pc),a0    ; access time string
  379.     bsr     conv2dig    ; convert hours into binary
  380.  
  381.     cmpi.b     #'A',4(a0)    ; is AM or PM indicated?
  382.     beq.s     nnta        ; branch if AM
  383.     cmpi.w     #12,d0        ; is hour between 12:00 and 12:59?
  384.     beq.s     nnta        ; yes, then skip
  385.     addi.w     #12,d0        ; adjust 1:00 into 13:00
  386.  
  387. nnta:    divu     #10,d0        ; split hours into digits
  388.     move.b     d0,(a2)+    ; store tens digit of hours
  389.     swap     d0        ; access ones digit
  390.     move.b     d0,(a2)+    ; store ones digit of hours
  391.  
  392.     move.b     (a0)+,(a2)+    ; move two digits of minutes
  393.     move.b     (a0)+,(a2)+
  394.  
  395.     move.b     (a0)+,(a2)+    ; move two digits of seconds
  396.     move.b     (a0)+,(a2)+
  397. *
  398. * --- translate ASCII digits into binary
  399. *
  400.     moveq     #13,d0        ; loop 14 bytes
  401. xclr:    andi.b     #15,-(a2)    ; convert ASCII digits to binary
  402.     dbra     d0,xclr
  403. *
  404. * --- begin clock update
  405. *
  406.     lea     buffer+14(a5),a2    ; address end of time data
  407.     moveq     #5,d0        ; command = stop clock
  408.     moveq     #0,d1        ; address = 0
  409.     bsr     w_clock    ; write command to stop clock
  410.  
  411.     moveq     #1,d0        ; command = set 24 hour mode
  412.     moveq     #30,d1        ; addr = 15
  413.     bsr     w_clock    ; write command
  414.  
  415.     moveq     #7,d0        ; command = interrupts off
  416.     moveq     #0,d1        ; addr = 0
  417.     bsr     w_clock    ; write command
  418. *
  419. * --- reprogram all registers from the table and start clock
  420. *
  421.     moveq     #14,d3        ; loop for 15 writes
  422.     moveq     #4,d1        ; begin addr = 2 (seconds register)
  423. sb2c:    move.b     -(a2),d0    ; get next time digit
  424.     bsr     w_clock    ; change the time
  425.     dbra     d3,sb2c
  426.     rts
  427.  
  428. * ==========================================================
  429. * ===== conv2dig :  convert decimal string into binary =====
  430. * ==========================================================
  431. *
  432. *    in:  A0.L = address of string
  433. *      out:  D0.L = binary value, range = 0..99
  434. *         A0.L = incremented by 2
  435. *            cc's : set by D0
  436. *  changed:  D1
  437. *
  438. *  This subroutine converts the two digit ASCII string pointed to by
  439. *  A0 into a binary value of the range 0..99.  The alternate entry
  440. *  point 'tenx' forms D0.L = 10*D0 + D1
  441. *
  442. conv2dig:
  443.     moveq     #15,d0        ; load mask for ten's digit
  444.     moveq     #15,d1        ; load mask for one's digit
  445.     and.b     (a0)+,d0    ; retrieve ten's digit
  446.     and.b     (a0)+,d1    ; retrieve one's digit
  447. *
  448. * --- form the result:   10*D0 + D1
  449. *
  450. tenx:    add.l     d0,d0        ; 2x
  451.     add.l     d0,d1        ; form 2x + y
  452.     add.l     d0,d0        ; 4x
  453.     add.l     d0,d0        ; 8x
  454.     add.l     d1,d0        ; result = 8x + 2x + y = 10x + y
  455.     rts
  456.  
  457. * ========================================
  458. * ===== chk_time : check time string =====
  459. * ========================================
  460. *
  461. *    in:  none
  462. *      out:  CC's : Z=1 if invalid string
  463. *  changed:  a0,a1,d0,d1,d2
  464. *
  465. *  This subroutine checks the time and date strings of the dialog for
  466. *  valid digits.  If any invalid digit is present the condition codes
  467. *  are set accordingly before exit.
  468. *
  469. t_vld:    dc.w    $0003    ; month x 10    = [0..1]
  470.     dc.w    $03ff    ; month x 1    = [0..9]
  471.     dc.w    $000f    ; date x 10    = [0..3]
  472.     dc.w    $03ff    ; date x 1    = [0..9]
  473.     dc.w    $0300    ; year x 10    = [8..9]
  474.     dc.w    $03ff    ; year x 1    = [0..9]
  475.     dc.w    -1
  476.     dc.w    $0003    ; hour x 10    = [0..1]
  477.     dc.w    $03ff    ; hour x 1    = [0..9]
  478.     dc.w    $003f    ; minute x 10    = [0..5]
  479.     dc.w    $03ff    ; minute x 1    = [0..9]
  480.     dc.w    $003f    ; second x 10    = [0..5]
  481.     dc.w    $03ff    ; second x 1    = [0..9]
  482. *
  483. chk_time:
  484.     lea    s_date(pc),a0    ; address the date string
  485.     lea    t_vld(pc),a1    ; point to table
  486.     moveq    #11,d2        ; loop count = 6 + 6 digits
  487. ct:    moveq    #15,d0        ; load mask
  488.     and.b    (a0)+,d0    ; get lower nibble of digit
  489.     move.w    (a1)+,d1    ; get validation bits
  490.     bpl.s    cx        ; branch unless validation = -1
  491.     lea    s_time(pc),a0    ; if -1, switch to time string
  492.     bra.s    ct        ; and continue
  493.  
  494. cx:    btst    d0,d1        ; is digit valid?
  495.     dbeq    d2,ct        ; loop if valid, stop if not
  496.     rts            ; return with cc's set
  497.  
  498. * ===================================
  499. * ===== set_time : set the time =====
  500. * ===================================
  501. *
  502. *    in:  none
  503. *      out:  none
  504. *  changed:
  505. *
  506. *  This routine checks the time and date strings of the dialog menu for
  507. *  validity.  If the strings are valid the information in them is used
  508. *  to generate the bit formats necessary to tell GEM and TOS what the
  509. *  time and date are.  Then the time and date are changed via system
  510. *  calls.
  511. *
  512. set_time:
  513.     bsr.s    chk_time    ; is the time and date valid?
  514.     beq.s    stxit        ; no, then exit
  515. *
  516. * --- convert date into BIOS format
  517. *
  518.     lea     s_date(pc),a0    ; address the date string
  519.     bsr.s     conv2dig    ; pull off the month
  520.     moveq     #$0F,d7    ; load 4 bit mask
  521.     and.w     d0,d7        ; 0000 0000 0000 mmmm
  522.  
  523.     bsr.s    conv2dig    ; pull off the day of the month
  524.     andi.w    #$001F,d0    ; mask down to 5 bits
  525.     lsl.w    #5,d7        ; shift month bits left 
  526.     or.w    d0,d7        ; 0000 000m mmmd dddd
  527.     
  528.     bsr    conv2dig    ; pull off the year
  529.     subi.w    #80,d0        ; convert 80 into 00
  530.     andi.w    #$007F,d0    ; mask down to 7 bits
  531.     ror.w    #7,d0        ; roll year to high end of word
  532.     or.w    d0,d7        ; yyyy yyym mmmd dddd
  533.  
  534.     swap    d7        ; save 'date' in high order bits of D7
  535. *
  536. * --- convert time into BIOS format
  537. *
  538.     lea     s_time(pc),a0    ; address time string
  539.     bsr    conv2dig    ; get HH
  540.     move.w    d0,d7        ; 0000 0000 000h hhhh
  541.  
  542.     bsr    conv2dig    ; get MM
  543.  
  544.     cmpi.b    #'A',(a0)    ; are we AM or PM?
  545.     beq.s    useAM        ; branch if AM
  546.     cmpi.w    #12,d7        ; are we 12:xx PM?
  547.     beq.s    useAM        ; yes, then don't correct
  548.     addi.w    #12,d7        ; else convert 1..11 into 13..23
  549.  
  550. useAM:    lsl.w    #6,d7        ; shift bits to make room for minutes
  551.     andi.w    #$003F,d0    ; mask minutes down to 6 bits
  552.     or.w    d0,d7        ; 0000 0hhh hhmm mmmm
  553. *
  554. * --- align time and set seconds to zero
  555. *
  556.     lsl.w    #5,d7        ; hhhh hmmm mmm0 0000
  557. *
  558. * --- tell GEM what the date and time is
  559. *
  560.     move.l    d7,-(sp)    ; pass [date:time] on stack
  561.     move.w    #22,-(sp)    ; function code
  562.     trap    #14        ; tell GEM what date/time is
  563.     addq.l    #6,sp        ; fix stack
  564. *
  565. * --- tell TOS what the time is
  566. *
  567.     move.w    d7,-(sp)    ; push "time"
  568.     move.w    #45,-(sp)    ; function code
  569.     trap    #1        ; tell TOS what time is
  570.     addq.l    #4,sp        ; fix stack
  571. *
  572. * --- tell TOS what the date is
  573. *
  574.     swap    d7        ; reorder [date:time] to [time:date]
  575.     move.w    d7,-(sp)    ; push "date"
  576.     move.w    #43,-(sp)    ; function code
  577.     trap    #1        ; tell TOS what date is
  578.     addq.l    #4,sp        ; fix stack
  579.  
  580.     moveq     #-1,d7        ; set condition codes to indicate OK
  581. stxit:    rts
  582.  
  583. * ==================================================
  584. * ===== dialog : display dialog and await exit =====
  585. * ==================================================
  586. *
  587. *       in:  A3.L = address of tree
  588. *      out:  D3.W = object ID causing exit
  589. *  changed:  A0, D0, ?
  590. *
  591. *  This subroutine reserves memory, draws the tree addressed by A3,
  592. *  processes the dialog, erases the dialog, sets the button which caused
  593. *  exit to non-selected, and frees up the reserved memory.  The object
  594. *  number of the button which caused exit is returned in D3.
  595. *
  596. dialog:    bsr     rsrv_win    ; reserve window space
  597.     bsr     treedraw    ; draw the tree
  598.     bsr     wfbutton    ; wait for response
  599.     bra     free_win    ; erase window
  600.  
  601. * ==================================================
  602. * ===== tstnclr :  Test and Clear SELECTED bit =====
  603. * ==================================================
  604. *
  605. *    in:  A3.L = tree address
  606. *            D3.W = object ID
  607. *      out:  D3.W = incremented by 1
  608. *            D0.W = object's state word anded with 1
  609. *            cc's : set by D0.W
  610. *  changed:  A0
  611. *
  612. *  This subroutine tests the SELECTED bit of the object number passed in
  613. *  D3 and increments D3.  The state of the bit is used to set a
  614. *  condition code before exit.
  615. *
  616. tstnclr:
  617.     bsr.s     objba        ; get address
  618.     moveq     #SELECTED,d0    ; load mask
  619.     and.w     (a0),d0    ; get bit
  620.     eor.w     d0,(a0)    ; clear bit if set
  621.     addq.w     #1,d3        ; update
  622.     tst.w     d0        ; set condition codes
  623.     rts
  624.  
  625. * ============================================
  626. * ===== objba   :  object bit address ========
  627. * ============================================
  628. *
  629. *    input:  A3.L = address of tree
  630. *            D3.W = object ID
  631. *      out:  A0.L = address of object's state word
  632. *  changed:  D0
  633. *
  634. *  This subroutine is used to form the address of the resource object's
  635. *  STATE word when given the resource tree address and object number.
  636. *
  637. objba:     move.w     d3,d0        ; copy object number
  638.      mulu     #24,d0        ; form 24 byte offset per object
  639.      lea     10(a3,d0.l),a0    ; STATE word is 10 bytes into object
  640.      rts
  641.  
  642. * ===========================================
  643. * ===== objbset :  object bit set ===========
  644. * ===========================================
  645. *
  646. *       in:  A3.L = address of tree
  647. *            D3.W = object id
  648. *            D4.W = bit mask
  649. *      out:  A0.L = address of object's state word
  650. *  changed:  none
  651. *
  652. *  This subroutine is used to 'OR' a bit mask with the STATE word of an
  653. *  object in a resource tree.  The alternate entry point 'setsel' is
  654. *  used when the 'SELECTED' bit is to be set.
  655. *
  656. setsel:     moveq     #1,d4        ; load SELECTED bit mask
  657. objbset: bsr.s     objba        ; form address
  658.      or.w     d4,(a0)    ; set bits by ORing
  659.      rts
  660.  
  661. * ==========================================
  662. * ===== rsrv_win : reserve window ==========
  663. * ==========================================
  664. *
  665. *       in:  A3.L = address of tree about to be displayed
  666. *      out:  none
  667. *  changed:  D0,D1,A0,A1
  668. *
  669. *  This routine first calls the FORM_CENTER routine to set the x,y,w,h 
  670. *  needed to center the window.  Then control drops into FREE_WIN which
  671. *  reserves the memory needed for the window size
  672. *
  673. rsrv_win:
  674.     lea     xx(a5),a1    ; addr temp area to receive x,y,w,h
  675.     bsr     _form_ce    ; calculate window center
  676.     moveq     #0,d0        ; pass code for reserving space
  677.     bra.s     fwep        ; enter free_win routine
  678.  
  679. * =======================================================
  680. * ===== free_win :  free up memory reserved earlier =====
  681. * =======================================================
  682. *
  683. *       in:  none
  684. *      out:  none
  685. *  changed:  D0,D1,A0,A1
  686. *
  687. *  This subroutine frees up memory which was reserved earlier.  The
  688. *  x,y,w,h clip rectangle was earlier stored at 'xx'.
  689. *
  690. free_win:
  691.     moveq     #3,d0        ; use code = 3, 
  692. fwep:    lea     xx(a5),a0    ; load pointer to x,y,w,h area
  693.     bra.s     _form_di    ; free memory
  694.     
  695. * =====================================
  696. * ===== objdraw :  draw an object =====
  697. * =====================================
  698. *
  699. *       in:  A3.L = address of tree
  700. *            D3.W = object to start with
  701. *      out:  none
  702. *  changed:  ?
  703. *
  704. *  This subroutine draws the resource tree starting at the object number
  705. *  given in D3 and for 5 levels of offspring.  The alternate entry point
  706. *  'treedraw' starts at object number 0 for drawing an entire tree.
  707. *
  708. treedraw:
  709.     moveq     #0,d3        ; for trees set object number to zero
  710. objdraw:
  711.     lea     xx(a5),a0    ; address x,y,w,h
  712.     moveq     #5,d1        ; pass 5 levels
  713.     move.w     d3,d0        ; pass object number in d0
  714.     bra     _objc_dr    ; draw
  715.  
  716. * =============================================== 
  717. * ===== wfbutton :  wait for a button ===========
  718. * ===============================================
  719. *
  720. *       in:  A3.L = tree address
  721. *            D0.W = object ID of editable text, 0 if none 
  722. *      out:  D3.W = ID of button causing exit
  723. *  changed:  ?
  724. *
  725. *  This routine calls the FORM_DO routine which processes the user
  726. *  interaction with a dialog.  Upon exit the object number which was
  727. *  used to exit the dialog is returned in D3.
  728. wfbutton:
  729.     moveq     #0,d0        ; set object number to 0
  730. wftext:    bsr.s     _form_do    ; process dialog
  731.     move.w     d0,d3        ; assign to exitobj
  732.     rts
  733.  
  734. * =================================
  735. * ===== _APPL_IN : initialize =====
  736. * =================================
  737. *
  738. *    in:  none
  739. *      out:  D0.W = ap_id or -1 if error
  740. *            cc's : set by D0.W
  741. *  changed:
  742. *
  743. *  This routine notifies GEM of an application and allows GEM to set up
  744. *  some housekeeping.  An application ID is assigned and we store it
  745. *  in our global variable area.
  746. *
  747. _appl_in:
  748.     moveq     #APPL_INI,d1    ; code = initialize
  749.     bsr.s     gem_ep        ; call GEM
  750.     move.w     d0,ap_id(a5)    ; store application ID
  751.     rts
  752.  
  753. * ===========================
  754. * ===== _APPL_EX : exit =====
  755. * ===========================
  756. *
  757. * in:    none
  758. * out:    d0.w = 0 on error
  759. *
  760. *  This routine notifies GEM of our intention to terminate.
  761. *
  762. _appl_ex:
  763.     moveq     #APPL_EXI,d1    ; code = exit
  764.     bra.s     gem_ep        ; call GEM
  765.  
  766. * ===================================
  767. * ===== _OBJC_DR :  Object Draw =====
  768. * ===================================
  769. *
  770. * in:    d0.w = start obj
  771. *    d1.w = depth
  772. *    a0.l = address of x,y,w,h clip limits [4 words]
  773. *    a3.l = tree address
  774. * out:    d0.w = 0 if error occurred
  775. *
  776. _objc_dr:
  777.     lea     int_in(a5),a1    ; address integer input array
  778.     move.w     d0,(a1)+    ; store starting object
  779.     move.w     d1,(a1)+    ; store drawing depth
  780.     move.l     (a0)+,(a1)+    ; store x and y
  781.     move.l     (a0)+,(a1)+    ; store w and h
  782.     move.l     a3,addr_in(a5)    ; store address of resource tree
  783.     moveq     #OBJC_DRA,d1    ; set function code = object draw
  784.     bra.s     gem_ep        ; call GEM
  785.  
  786. * ======================================
  787. * ===== _FORM_DO :  Process Dialog =====
  788. * ======================================
  789. *
  790. * in:    d0.w = start object, a3.l = tree address
  791. * out:    d0.w = exit object
  792. *
  793. _form_do:
  794.     move.l     a3,a0        ; pass tree address in A0
  795.     moveq   #FORM_DO,d1    ; function = FORM DO
  796.     bra.s     call_gem    ; call GEM
  797.  
  798. * ==========================================
  799. * ===== _FORM_DI : Dialog Housekeeping =====
  800. * ==========================================
  801. *
  802. * in:    d0.w = action [0=reserve, 1=grow, 2=shrink, 3=free]
  803. *    a0.l = address of x,y,w,h limits [4 words]
  804. * out:    d0.w = 0 if an error occurred
  805. *
  806. *  This routine is used to reserve or release memory or to draw a
  807. *  growing or shrinking box.  The operation code is passed in D0 and
  808. *  the second x,y,w,h dimensions are pointed to by a0.  This routine
  809. *  is currently hard coded so that the first set of x,y,w,h points is
  810. *  always zero.
  811. *
  812. _form_di:
  813.     lea     int_in(a5),a1    ; address integer input array
  814.     move.w     d0,(a1)+    ; store operation code
  815.     clr.l     (a1)+        ; x1 = 0, y1 = 0
  816.     clr.l     (a1)+        ; w1 = 0, h1 = 0
  817.     move.l     (a0)+,(a1)+    ; store x2, y2
  818.     move.l     (a0)+,(a1)+    ; store w2, h2
  819.     moveq     #FORM_DIA,d1    ; function = FORM_DIALOG
  820.     bra.s     gem_ep        ; call GEM
  821.  
  822. * ===========================================
  823. * ===== _FORM_AL :  Process Alert Boxes =====
  824. * ===========================================
  825. *
  826. * in:    d0.w = default exit button, a0 = alert string address
  827. * out:    d0.w = exit button used, 1=first, 2=second, etc.
  828. *
  829. *  This routine displays and processes user interaction with the alert
  830. *  box.  The address of the alert string is passed in A0 and the default
  831. *  exit button if more than one is present is passed in D0.  The
  832. *  alternate entry point '_alert' sets the default exit button to 1.
  833. *
  834. _alert:     moveq     #1,d0        ; default exit button = 1 (leftmost)
  835. _form_al:
  836.      moveq     #FORM_ALE,d1    ; function code
  837.      bra.s     call_gem    ; call GEM
  838.  
  839. * ==============================================
  840. * ===== _FORM_CE : Calculate box centering =====
  841. * ==============================================
  842. *
  843. * in:    a3.l = address of tree
  844. *    a1.l = addr of area to store x,y,w,h of centered tree
  845. * out:    none
  846. *
  847. *  This routine calculates the x and y coordinates necessary to center
  848. *  the resource treee addressed by A3 on the screen.  The x,y,w,h
  849. *  coordinates necessary for a clip rectangle are returned and stored
  850. *  at the address passed in A1.
  851. *
  852. _form_ce:
  853.      move.l     a3,a0        ; pass tree address in A0
  854.      moveq     #FORM_CEN,d1    ; function = form center
  855.      bsr.s     call_gem    ; call gem
  856.      lea     int_out+2(a5),a0 ; access x,y,w,h returned
  857.      move.l     (a0)+,(a1)+    ; store x,y
  858.      move.l     (a0)+,(a1)+    ; store w,h
  859.      rts
  860.  
  861. * ========================================
  862. * ===== _GRAF_MO : Change Mouse Form =====
  863. * ========================================
  864. *
  865. *    in:    d0.w = code of mouse form desired    
  866. *      out:    d0.w = 0 if error    
  867. *  changed:
  868. *
  869. *  This routine changes the form of the mouse pointer used.  It can also
  870. *  be used to hide and unhide the mouse.
  871. *
  872. _mouse:     moveq     #0,d0        set mouse form to pointer
  873. _graf_mo:
  874.     suba.l     a0,a0     
  875.     moveq     #GRAF_MOU,d1
  876.     
  877. * =======================================================
  878. * ===== call_gem : set up parameters for a gem call =====
  879. * =======================================================
  880. *
  881. *    in:    D1.W = op code number
  882. *               D0.W = optional int_in[0]
  883. *            A0.L = optional addr_in[0] 
  884. *      out:    D0.W = returned value from int_out[0], if any 
  885. *  changed:    A0,A1,D1
  886. *
  887. *  This subroutine uses the op code number passed in D1 to
  888. *  look up the number of integers and addresses in and out for the
  889. *  GEM call.  This information is then stored in the 'CONTROL' array
  890. *  located in the dynamic storage area.  Then GEM call is then 
  891. *  performed and a possible return code is loaded into D0 before exit.
  892. *  
  893. call_gem:
  894.     move.l    a0,addr_in(a5)  in case there's an address in
  895.     move.w    d0,int_in(a5)    in case there's an integer in
  896.  
  897. gem_ep:    movem.l    d2-d7/a1-a6,-(sp)    ; save registers
  898.     add.w    d1,d1            ; function x 2
  899.     add.w    d1,d1            ; function x 4
  900.     lea    gemtbl(pc,d1.w),a0    ; form address of entry
  901. *
  902. * --- transfer opcode, integers in, integers out, and addresses
  903. *
  904.     lea    control(a5),a1    ; address control array
  905.     moveq    #0,d0        ; form a zero
  906.     movep.l    d0,0(a1)    ; clear upper bytes of control[0..3]
  907.     move.l    (a0),d0        ; get bytes from table entry
  908.     movep.l    d0,1(a1)    ; fill lower bytes of control[0..3]
  909.     clr.w    8(a1)        ; set control[4] to zero
  910. *
  911. * --- perform the GEM/AES call
  912. *
  913.     move.l    a5,d1        ; pass address of 'control' array in D1
  914.     move.w    #200,d0        ; pass special function number in D0
  915.     trap    #2        ; call the system
  916.     movem.l    (sp)+,d2-d7/a1-a6 ; restore registers
  917.     moveq    #0,d0        ; clear upper portion of register
  918.     move.w    int_out(a5),d0    ; retrieve a return value
  919.     rts
  920. *
  921. * --- Table of control parameters for AES calls
  922. *
  923. *     each entry has:  AES/GEM function number
  924. *                      number of integers (words) in
  925. *                      number of integers (words) out
  926. *                      number of address (longs) in
  927. *
  928. gemtbl:    dc.b    10,0,1,0    ; APPL_INIT
  929.     dc.b    19,0,1,0    ; APPL_EXIT
  930.     dc.b    42,6,1,1    ; OBJC_DRAW
  931.     dc.b    50,1,1,1    ; FORM_DO
  932.     dc.b    51,9,1,0    ; FORM_DIAL
  933.     dc.b    52,1,1,1    ; FORM_ALERT
  934.     dc.b    54,0,5,1    ; FORM_CENTER
  935.     dc.b    78,1,1,1    ; GRAF_MOUSE
  936.     
  937. *
  938. * --- strings for alerts
  939. *
  940. warning: dc.b    '[3][ Clock missing or | not working ][ OK ]',0
  941. badtime: dc.b    '[3][Bad Time or Date,|please retry][ OK ]',0
  942. *
  943. * --- strings for dialog
  944. *
  945. null:    dc.b    0
  946.  
  947. s_time:    dc.b    '122345A',0
  948. s1:    dc.b    'TIME = __:__:__ _M',0
  949. s2:    dc.b    '999999F',0
  950.  
  951. s_date:    dc.b    '071486',0
  952. s4:    dc.b    'DATE = __/__/__',0
  953. s5:    dc.b    '999999',0
  954.  
  955. s6:    dc.b    'SUN',0
  956. s7:    dc.b    'MON',0
  957. s8:    dc.b    'TUE',0
  958. s9:    dc.b    'WED',0
  959. s10:    dc.b    'THU',0
  960. s11:    dc.b    'FRI',0
  961. s12:    dc.b    'SAT',0
  962.  
  963. s13:    dc.b    'SET',0
  964. s14:    dc.b    'EXIT',0
  965. s15:    dc.b    'CLOCK CARTRIDGE',0
  966. *
  967. * ========== text info structures ========== *
  968. *
  969. *  each entry:   L - pointer to text
  970. *                L - pointer to template
  971. *                L - pointer to validation string
  972. *                W - font to be used, 3=normal, 5=small
  973. *                W - 6
  974. *                W - justification (left, center, right)
  975. *                W - color code
  976. *                W - 0
  977. *                W - border thickness ( + outward, - inward )
  978. *                W - length of text (including null)
  979. *                W - length of template (including null)
  980. *              =====
  981. *               28 bytes
  982. *
  983. *
  984. * --- text info blocks
  985. *
  986. ti0:    dc.l    s_time,s1,s2    ; time        
  987.     dc.w    3,6,0,$1180
  988.     dc.w    0,-1,8,19
  989.  
  990. ti1:    dc.l    s_date,s4,s5    ; date
  991.     dc.w    3,6,0,$1180
  992.     dc.w    0,-1,7,16
  993.  
  994. ti2:    dc.l    s15,null,null    ; title string
  995.     dc.w    3,6,2,$1180
  996.     dc.w    0,-3,16,1
  997. *
  998. * ========== object structures ========== *
  999. *
  1000. * each entry:  W - ID of next sibling (-1 if none)
  1001. *              W - ID of first offspring (-1 if none)
  1002. *              W - ID of last offspring (-1 if none)
  1003. *              W - type of object
  1004. *              W - object flags
  1005. *              W - state flags (selected, open, etc)
  1006. *              L - <expansion>
  1007. *              W - x position of upper left corner (relative to parent)
  1008. *              W - y position of upper left corner
  1009. *              W - width in pixels
  1010. *              W - height in pixels
  1011. *            =====
  1012. *             24 bytes
  1013. *
  1014. * --- object types:
  1015. *
  1016. BOX     EQU    20    ; box
  1017. TXT     EQU    21    ; text
  1018. BOXTEXT     EQU    22    ; text within a box
  1019. IMAGE     EQU    23    ; bit image
  1020. PROGDEF     EQU    24    ; programmer defined
  1021. IBOX     EQU    25    ; invisible box
  1022. BUTTON     EQU    26    ; text within a button
  1023. BOXCHAR     EQU    27    ; single char within a button
  1024. STRING     EQU    28    ; string
  1025. ETEXT     EQU    29    ; editable text
  1026. EBOXTEXT EQU    30    ; editable text within a box
  1027. ICON     EQU    31    ; icon image
  1028. TITLE     EQU    32    ; string used in menu titles
  1029. *
  1030. * --- object option flags:
  1031. *
  1032. NONE     EQU    $0000    ; no option
  1033. SLECTBLE EQU    $0001    ; SLECTBLE
  1034. DEFAULT     EQU    $0002    ; default for <CR>
  1035. EXIT     EQU    $0004    ; causes exit when selected
  1036. EDITABLE EQU    $0008    ; editable text
  1037. RADIOB     EQU    $0010    ; radio button
  1038. LASTOB     EQU    $0020    ; last object in tree
  1039. *
  1040. * --- object states:
  1041. *
  1042. NORMAL     EQU    $0000    ; nothing special
  1043. SELECTED EQU    $0001    ; has been selected by the mouse button
  1044. DISABLED EQU    $0008    ; can't be selected
  1045. OUTLINED EQU    $0010    ; shows up as outlined
  1046. SHADOWED EQU    $0020    ; shows up as casting a shadow
  1047. *
  1048. * ===== RESOURCE TREE:  ================================================
  1049. *
  1050. tree:    dc.w    -1,01,01,BOX        ; outermost box
  1051.     dc.w    NONE,NORMAL
  1052.     dc.l    $00011100
  1053.     dc.w    0,0,262,174
  1054. * obj 1
  1055.     dc.w    00,02,14,BOX
  1056.     dc.w    SLECTBLE+EXIT,NORMAL    ; inner framing box
  1057.     dc.l    $00FD1103
  1058.     dc.w    7,7,248,160
  1059. * obj 2
  1060.     dc.w    03,-1,-1,ETEXT        ; editable date string
  1061.     dc.w    EDITABLE,NORMAL
  1062.     dc.l    ti1
  1063.     dc.w    79,55,120,16
  1064. * obj 3
  1065.     dc.w    04,-1,-1,ETEXT        ; editable time string
  1066.     dc.w    EDITABLE,NORMAL
  1067.     dc.l    ti0
  1068.     dc.w    79,78,144,16
  1069. * obj 4
  1070.     dc.w    12,05,11,BOX        ; box surrounding radio buttons
  1071.     dc.w    NONE,NORMAL
  1072.     dc.l    $00FF1100
  1073.     dc.w    16,16,43,126
  1074. * obj 5
  1075.     dc.w    06,-1,-1,BUTTON        ; radio button for SUN
  1076.     dc.w    (RADIOB+SLECTBLE),NORMAL
  1077.     dc.l    s6
  1078.     dc.w    1,1,41,16
  1079. * obj 6
  1080.     dc.w    07,-1,-1,BUTTON        ; MON
  1081.     dc.w    (RADIOB+SLECTBLE),NORMAL
  1082.     dc.l    s7
  1083.     dc.w    1,19,41,16
  1084. * obj 7
  1085.     dc.w    08,-1,-1,BUTTON        ; TUE
  1086.     dc.w    (RADIOB+SLECTBLE),NORMAL
  1087.     dc.l    s8
  1088.     dc.w    1,37,41,16
  1089. * obj 8
  1090.     dc.w    09,-1,-1,BUTTON        ; WED
  1091.     dc.w    (RADIOB+SLECTBLE),NORMAL
  1092.     dc.l    s9
  1093.     dc.w    1,55,41,16
  1094. * obj 9
  1095.     dc.w    10,-1,-1,BUTTON        ; THU
  1096.     dc.w    (RADIOB+SLECTBLE),NORMAL
  1097.     dc.l    s10
  1098.     dc.w    1,73,41,16
  1099. * obj 10
  1100.     dc.w    11,-1,-1,BUTTON        ; FRI
  1101.     dc.w    (RADIOB+SLECTBLE),NORMAL
  1102.     dc.l    s11
  1103.     dc.w    1,91,41,16
  1104. * obj 11
  1105.     dc.w    04,-1,-1,BUTTON        ; SAT
  1106.     dc.w    (RADIOB+SLECTBLE),NORMAL
  1107.     dc.l    s12
  1108.     dc.w    1,109,41,16
  1109. * obj 12
  1110.     dc.w    13,-1,-1,BUTTON        ; 'SET' button
  1111.     dc.w    5,SHADOWED
  1112.     dc.l    s13
  1113.     dc.w    72,112,64,16
  1114. * obj 13
  1115.     dc.w    14,-1,-1,BUTTON        ; 'EXIT' button
  1116.     dc.w    5,SHADOWED
  1117.     dc.l    s14
  1118.     dc.w    160,112,64,16
  1119. * obj 14
  1120.     dc.w    01,-1,-1,BOXTEXT    ; title in a box
  1121.     dc.w    LASTOB+SLECTBLE+EXIT,NORMAL
  1122.     dc.l    ti2
  1123.     dc.w    80,16,136,16
  1124. *
  1125. * --- dynamic storage area begins at end of program
  1126. *
  1127. *  The dynamic storage is an uninitialized temporary data area that
  1128. *  begins at the end of the program.  It is used for the stack and all
  1129. *  variables that do not need to be initialized prior to program
  1130. *  execution.  Use of a dynamic storage area reduces the disk space
  1131. *  requirements of the program.
  1132. *
  1133. storage: nop
  1134.         end
  1135.